You can create heap zones as subzones of your application heap zone or (in rare instances) either in space reserved for the application global variables or on the stack. You can also create heap zones in a block of temporary memory or within the system heap zone. This section describes how to create new heap zones by calling the InitZone procedure.
Most applications do not need to create heap zones.
To create a new heap zone in the application heap, you must allocate nonrelocatable blocks in your application heap to hold new subzones of the application heap. In addition to being able to create subzones of the application zone, you can create subzones of any other zone to which you have access, including a zone that is itself a subzone of another zone.
You create a heap zone by calling the InitZone procedure, which takes four parameters. The first parameter specifies a grow-zone function for the new zone, or NIL if you do not want the zone to have a grow-zone function. The second parameter specifies the number of new master pointers that you want each block of master pointers in the zone to contain. The InitZone procedure allocates one such block to start with, and you can allocate more by calling the MoreMasters procedure. The third and fourth parameters specify, respectively, the first byte beyond the end of the new zone and the first byte of the zone.
When initializing a zone with the InitZone procedure, make sure that you are subdividing the current zone. When InitZone returns, the new zone becomes current. Thus, if you subdivide the application zone into several subzones, you must call SetZone(ApplicationZone) before you create the second and each of the subsequent subzones. Listing 5 shows a technique for creating a single subzone of the original application zone, assuming that the application zone is the current zone. The technique for subdividing subzones is similar.
Listing 5 Creating a subzone of the original application heap zone
FUNCTION CreateSubZone: THz;
CONST
kZoneSize = 10240; {10K zone}
kNumMasterPointers = 16; {num of master ptrs for new zone}
VAR
start: Ptr; {first byte in zone}
limit: Ptr; {first byte beyond zone}
BEGIN
start := NewPtr(kZoneSize); {allocate storage for zone}
IF MemError <> noErr THEN
BEGIN {allocation successful}
limit := Ptr(ORD4(start) + kZoneSize);
{compute byte beyond end of zone}
InitZone(NIL, kNumMasterPointers, limit, start);
{initialize zone header, trailer}
END;
CreateSubZone := THz(start); {cast storage to a zone pointer}
END;
To create a subzone in the system heap zone, you can call SetZone(SystemZone) at the beginning of the procedure in Listing 5 . You might find this technique useful if you are implementing a system extension but want to manage your extension's memory much as you manage memory in an application. Instead of simply allocating blocks in the system heap, you can make your zone current whenever your extension is executed. Then, you can call regular Memory Manager routines to allocate memory in your subzone of the system heap, and you can compact and purge your subzone without compacting and purging the entire system heap zone.
When you allocate memory for a subzone, you must allocate that memory in a nonrelocatable block (as in Listing 5 ) or in a locked relocatable block. If you create a subzone within an unlocked relocatable block, the Memory Manager might move your entire subzone during memory operations in the zone containing your subzone. If so, any references to nonrelocatable blocks that you allocated in the subzone would become invalid. Even handles to relocatable blocks in the subzone would no longer be valid, because the Memory Manager does not update the handles' master pointers correctly. This happens because the Memory Manager views a subzone of another zone as a single block. If that subzone is a relocatable block, the Memory Manager updates only that block's master pointer when moving it, and does not update the block's contents (that is, the blocks allocated within the subzone).
If you use a block of temporary memory as a heap zone, you must lock the temporary memory immediately after allocating it. Then, you can pass to InitZone a dereferenced copy of a handle to the temporary memory. If you find (after a call to the Gestalt function) that temporary memory handles are not real, then you must dispose of the new zone before any calls to GetNextEvent or WaitNextEvent . You must dispose of the new zone because you cannot lock a handle to temporary memory across event calls if the handle is not real.
Once you have created a subzone as a nonrelocatable block or a locked relocatable block, you can allocate both relocatable and nonrelocatable blocks within it. Although the Memory Manager can move such relocatable blocks only within the subzone, it correctly updates those blocks' master pointers, which are also in the subzone.